﻿using Shop.Model.DB;
using Shop.RemoteModel.SpecTemplate.Model;
using Shop.Repository;
using SqlSugar;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;

namespace Shop.Collect.lmpl
{
    internal class SpecsTemplateCollect : ISpecsTemplateCollect
    {
        private readonly ISpecsTemplateRepository _Repository;

        public SpecsTemplateCollect (ISpecsTemplateRepository repostory)
        {
            this._Repository = repostory;
        }
        public long Add (SpecTemplateAdd datum)
        {
            if (this._Repository.IsExist(c => c.TemplateId == datum.TemplateId && c.SpecName == datum.SpecName))
            {
                throw new ErrorException("shop.specs.name.repeat");
            }
            DBSpecsTemplate add = datum.ConvertMap<SpecTemplateAdd, DBSpecsTemplate>();
            add.Sort = this._Repository.Max(c => c.TemplateId == datum.TemplateId, c => c.Sort) + 1;
            return this._Repository.Add(add);
        }
        public SpecTemplateItem[] GetItems (long templateId, string query)
        {
            if (query.IsNull())
            {
                return this._Repository.Gets<SpecTemplateItem>(a => a.TemplateId == templateId && a.IsEnable, "Sort");
            }
            return this._Repository.Gets<SpecTemplateItem>(a => a.TemplateId == templateId && a.IsEnable && a.SpecName.Contains(query), "Sort");
        }
        public SpecTemplateDto[] Gets (long templateId)
        {
            return this._Repository.Gets<SpecTemplateDto>(a => a.TemplateId == templateId, "Sort");
        }
        public Dictionary<long, SpecTemplateItem[]> GetSpecs (long[] templateId)
        {
            return this._Repository.Gets(a => templateId.Contains(a.TemplateId) && a.IsEnable, a => new
            {
                a.Id,
                a.TemplateId,
                a.SpecName,
                a.SpecIcon,
                a.Sort
            }).GroupBy(a => a.TemplateId).ToDictionary(a => a.Key, a => a.OrderBy(c => c.Sort).Select(c => new SpecTemplateItem
            {
                Id = c.Id,
                SpecName = c.SpecName,
                SpecIcon = c.SpecIcon
            }).ToArray());
        }
        public Dictionary<long, string[]> GetSpecName (long[] templateId)
        {
            return this._Repository.Gets(a => templateId.Contains(a.TemplateId) && a.IsEnable, a => new
            {
                a.TemplateId,
                a.SpecName
            }).GroupBy(a => a.TemplateId).ToDictionary(a => a.Key, a => a.Select(c => c.SpecName).ToArray());
        }
        public DBSpecsTemplate Get (long id)
        {
            return this._Repository.Get(id);
        }
        public Result Get<Result> (long id) where Result : class
        {
            return this._Repository.Get<Result>(id);
        }
        public void SetIsEnable (DBSpecsTemplate source, bool isEnable)
        {
            if (source.IsEnable == isEnable)
            {
                return;
            }
            this._Repository.SetIsEnable(source.Id, isEnable);
        }
        public void Delete (DBSpecsTemplate source)
        {
            if (source.IsEnable)
            {
                throw new ErrorException("shop.spec.already.enable");
            }
            this._Repository.Delete(source.Id);
        }
        public bool Set (DBSpecsTemplate source, SpecTemplateSet set)
        {
            if (source.SpecName != set.SpecName && this._Repository.IsExist(c => c.TemplateId == source.TemplateId && c.SpecName == set.SpecName))
            {
                throw new ErrorException("shop.spec.name.repeat");
            }
            return this._Repository.Update(source, set);
        }

        public void Clear (long templateId)
        {
            long[] ids = this._Repository.Gets(a => a.TemplateId == templateId, a => a.Id);
            if (ids.IsNull())
            {
                return;
            }
            this._Repository.Delete(ids);
        }
        public Dictionary<long, int> SetSort (DBSpecsTemplate template, int sort)
        {
            int num = template.Sort - sort;
            Dictionary<long, int> sorts = new Dictionary<long, int>()
            {
               {template.Id,sort }
            };
            if (Math.Abs(num) == 1)
            {
                long id = this._Repository.Get(a => a.TemplateId == template.TemplateId && a.Sort == sort, a => a.Id);
                if (id != 0)
                {
                    sorts.Add(id, template.Sort);
                }
            }
            else
            {
                int begin = template.Sort;
                int end = sort;
                if (begin > end)
                {
                    begin = sort;
                    end = template.Sort - 1;
                }
                else
                {
                    begin += 1;
                }
                var datas = this._Repository.Gets(a => a.TemplateId == template.TemplateId && SqlFunc.Between(a.Sort, begin, end), a => new
                {
                    a.Id,
                    a.Sort
                }).OrderBy(a => a.Sort).ToArray();
                if (!datas.IsNull() && datas[0].Sort == sort)
                {
                    num = num > 0 ? 1 : -1;
                    for (int i = 0; i < datas.Length; i++)
                    {
                        int next = i + 1;
                        var t = datas[i];
                        int s = t.Sort + num;
                        sorts.Add(t.Id, s);
                        if (next != datas.Length && datas[next].Sort != s)
                        {
                            break;
                        }
                    }
                }
            }
            this._Repository.SetSort(sorts);
            return sorts;
        }
        public void CheckIsNull (long id)
        {
            if (!this._Repository.IsExist(c => c.TemplateId == id))
            {
                throw new ErrorException("shop.group.spec.null");
            }
        }
    }
}
